《剑指offer》 25. 合并两个排序的链表

notes:归并排序用于两个有序链表的排序很有效果,此题目重点应该是在想到需要一个额外的伪头节点

题目描述

输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。

示例1:

1
2
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

限制:

1
0 <= 链表长度 <= 1000

方法 归并排序+伪头节点

思路

两个有序链表的排序很显然应该用归并排序进行解题。

我们需要一个头节点作为找到我们合并后链表的首节点的凭据,同时也是作为我们进行递归时移动的指针。

根据归并排序,当我们其中一个链表已经遍历完毕,另一个链表还没有遍历完毕时,不需要重新遍历另一个链表,利用链表的性质直接将其接在我们的新链表后面就可以了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode *newlist = new ListNode(-1);
ListNode * head = newlist;
while(l1!=NULL && l2!=NULL){
if(l1->val <= l2->val){
newlist->next = l1;
l1 = l1->next;
}else{
newlist->next = l2;
l2 = l2->next;
}
newlist = newlist->next;
}
if(l1)
newlist->next = l1;
if(l2)
newlist->next = l2;
return head->next;
}
};

复杂度分析

  • 时间复杂度$O(n)$。遍历两个链表,线性时间复杂度
  • 空间复杂度$O(1)$。只使用了一个伪头节点,常数空间复杂度。